package com.appcenter.application.service;

import com.appcenter.application.dto.apps.AppDto;
import com.appcenter.application.dto.jobs.JobDto;
import com.appcenter.application.dto.menu.MenuDto;
import com.appcenter.application.dto.orgs.OrgDto;
import com.appcenter.application.dto.permissions.PermissionsDto;
import com.appcenter.application.dto.roles.RoleDto;
import com.appcenter.application.dto.users.UserApiDto;
import com.appcenter.application.dto.users.UserDto;
import com.appcenter.application.expand.ObjectFinal;
import com.appcenter.application.input.app.GetAppsInput;
import com.appcenter.application.input.externalapi.GetMenusInput;
import com.appcenter.application.input.permission.*;
import com.appcenter.application.mapper.*;
import com.appcenter.application.model.*;
import com.appcenter.application.output.externalapi.GetMenusOutput;
import com.appcenter.application.output.permission.*;
import com.appcenter.jz.Logger.BusinessLogger;
import com.appcenter.jz.Logger.LoggerGenre;
import com.appcenter.jz.app.CurrentUser;
import com.appcenter.jz.unit.ListUtils;
import com.appcenter.jz.unit.ObjectUnit;
import com.appcenter.jz.config.ErrorJsonResult;
import com.appcenter.jz.page.PagedResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.xml.crypto.Data;
import java.util.*;
import java.util.stream.Collectors;

import static org.apache.http.util.TextUtils.isBlank;

@Service
public class PermissionService {
    @Autowired
    PermissionsMapper permissionsMapper;

    @Autowired
    PermissionRelationsMapper permissionRelationsMapper;

    @Autowired
    AppsMapper appsMapper;

    @Autowired
    UsersMapper usersMapper;

    @Autowired
    ObjectFinal objectFinal;

    @Autowired
    PermissionService permissionService;

    @Autowired
    OrgsMapper orgsMapper;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

//    @CacheEvict(cacheNames = "basewarrant", allEntries = true)
//    @Transactional
    /**
     *  创建人:Coke
     *  备注: 创建权限信息
     *  时间: 2019/4/26 14:02 
     *  参数: 
     */
    public CreatePermissionOutput CreatePermission(CreatePermissionInput input) throws Exception {
        CreatePermissionOutput output = new CreatePermissionOutput();

        int NameCount = permissionsMapper.getNameCount(input.getItem().getAppId(), input.getItem().getPermissionCode()).size();

        if (NameCount > 0) {
            throw new ErrorJsonResult("1000051", "权限编号已存在！");
        }
        PermissionsDto permissionsDto = input.getItem();
        String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();
        permissionsDto.setId(uuid);
        permissionsDto.setCreateTime(new Date());
        permissionsDto.setCreateUserId(CurrentUser.getUserId());
        permissionsDto.setValidStatus(true);

        if (isBlank(permissionsDto.getParentId())) {
            permissionsDto.setLevel((long) 1);
            permissionsDto.setIdPath(uuid);
        } else {
            Permissions permission = permissionsMapper.selectByPrimaryKey(permissionsDto.getParentId());
            permissionsDto.setLevel(permission.getLevel() + 1);
            permissionsDto.setIdPath(permission.getIdPath() + "/" + uuid);
        }

        Permissions Permission = new Permissions();
        BeanUtils.copyProperties(permissionsDto, Permission);
        BusinessLogger.Info(LoggerGenre.Add, "添加权限", input);
        permissionsMapper.insertSelective(Permission);

        output.setItem(permissionsDto);
        return output;
    }

//    @CacheEvict(cacheNames = "basewarrant", allEntries = true)
//    @Transactional
    /**
     *  创建人:Coke
     *  备注: 删除权限信息
     *  时间: 2019/4/26 14:02 
     *  参数: 
     */
    public DeletePermissionOutput DeletePermission(DeletePermissionInput input) throws Exception {
        DeletePermissionOutput output = new DeletePermissionOutput();

        Permissions permission = permissionsMapper.selectByPrimaryKey(input.getItem().getId());
        List<Permissions> delPermissions = new ArrayList<>();
        if (permission != null) {
            Example examplePer = new Example(Permissions.class);
            Example.Criteria criteria = examplePer.createCriteria();
            criteria.andLike("idPath", permission.getIdPath() + "%");
            delPermissions = permissionsMapper.selectByExample(examplePer);
        }
        for (Permissions per : delPermissions) {
            per.setValidStatus(false);
            permissionsMapper.updateByPrimaryKey(per);

            //删除权限的落地权限
            Example examplePermissionRelation = new Example(PermissionGroupRelations.class);
            Example.Criteria criteriaPermissionRelation = examplePermissionRelation.createCriteria();
            criteriaPermissionRelation.andEqualTo("permissionId", per.getId());

            BusinessLogger.Info(LoggerGenre.Delete, "删除权限", input);
            //  PermissionsDto item = new PermissionsDto();
        }
        PermissionsDto dto = new PermissionsDto();
        BeanUtils.copyProperties(permission, dto);
        output.setItem(dto);
        return output;
    }

//    @CacheEvict(cacheNames = "basewarrant", allEntries = true)
//    @Transactional
    /**
     *  创建人:Coke
     *  备注: 修改权限信息
     *  时间: 2019/4/26 14:02 
     *  参数: 
     */
    public EditPermissionOutput EditPermission(EditPermissionInput input) throws Exception {
        EditPermissionOutput output = new EditPermissionOutput();
        int NameCount = permissionsMapper.getNameCountNoId(input.getItem().getAppId(), input.getItem().getPermissionCode(), input.getItem().getId()).size();

        if (NameCount > 0) {
            throw new ErrorJsonResult("1000051", "权限编号已存在！");
        }
        Permissions Permission = permissionsMapper.selectByPrimaryKey(input.getItem().getId());
        // Permission.setAppId(input.getItem().getAppId());
        Permission.setPermissionCode(input.getItem().getPermissionCode());
        Permission.setPermissionName(input.getItem().getPermissionName());
        Permission.setDescription(input.getItem().getDescription());
        Permission.setListOrder(input.getItem().getListOrder());
        Permission.setIcon(input.getItem().getIcon());
        Permission.setUrl(input.getItem().getUrl());
        Permission.setVisible(input.getItem().getVisible());
        Permission.setPermissionType(input.getItem().getPermissionType());

        BusinessLogger.Info(LoggerGenre.Update, "修改权限", input);
        permissionsMapper.updateByPrimaryKey(Permission);

        PermissionsDto item = new PermissionsDto();
        BeanUtils.copyProperties(Permission, item);
        output.setItem(item);
        return output;
    }


    //    @Transactional
    /**
     *  创建人:Coke
     *  备注: 获取权限信息
     *  时间: 2019/4/26 14:02 
     *  参数: 
     */
    public GetPermissionsOutput GetPermissions(GetPermissionsInput input) throws Exception {
        GetPermissionsOutput output = new GetPermissionsOutput();
        if (isBlank(input.getAppCode())) input.setAppCode("");
        List<Permissions> permissions = permissionsMapper.searchPermissionList(input);
        Map<String, PermissionsDto> parentPermissionDtoDic = new HashMap<String, PermissionsDto>();
        List<PermissionsDto> permissionDtos = new ArrayList<PermissionsDto>();

        if (permissions != null && permissions.size() > 0) {
            for (int i = 0; i < permissions.size(); i++) {
                PermissionsDto permissionsDto = new PermissionsDto();
                BeanUtils.copyProperties(permissions.get(i), permissionsDto);

                if (permissions.get(i).getParentId() == null || !parentPermissionDtoDic.containsKey(permissions.get(i).getParentId())) {
                    permissionDtos.add(permissionsDto);
                } else {
                    PermissionsDto parentPermissionDto = parentPermissionDtoDic.get(permissionsDto.getParentId());
                    if (parentPermissionDto.getChildren() == null) {
                        parentPermissionDto.setChildren(new ArrayList<PermissionsDto>());
                    }
                    parentPermissionDto.getChildren().add(permissionsDto);
                }
                parentPermissionDtoDic.put(permissionsDto.getId(), permissionsDto);
            }
        }
        BusinessLogger.Info(LoggerGenre.View, "获取权限树", input);
        output.setPermissions(permissionDtos);
        return output;
    }

    //    @Transactional
    /**
     *  创建人:Coke
     *  备注: 加载权限信息
     *  时间: 2019/4/26 14:02 
     *  参数: 
     */
    public PageLoadOutput PageLoad(PageLoadInput input) throws Exception {
        PageLoadOutput output = new PageLoadOutput();

        GetAppsInput getAppsInput = new GetAppsInput();
        List<AppDto> apps = objectFinal.GetPermissionApps(ObjectFinal.APP_CODE, CurrentUser.getUserCode());
        output.setApps(apps);
        // if (apps != null && apps.size() > 0) {
        //     input.setAppCode(apps.get(0).getAppCode());
        //     //GetPermissionsOutput getPermissions = GetPermissions(input);
        //     // output.setPermissions(getPermissions.getPermissions());
        //     List <PermissionsDto> ls = new ArrayList <>();
        //     output.setItems(new PagedResult <PermissionsDto>(ls, ls.size()));
        // }
        List<PermissionsDto> ls = new ArrayList<>();
        output.setItems(new PagedResult<PermissionsDto>(ls, ls.size()));
        return output;
    }

    //--------PermissionService---------
//    @Cacheable(value = "basewarrant", keyGenerator = "ObjectKey")
    /**
     *  创建人:Coke
     *  备注: 获取权限信息
     *  时间: 2019/4/26 14:03 
     *  参数: 
     */
    public GetPermissionsServiceOutput qGetPermissions(GetPermissionsServiceInput input) throws Exception {
        GetPermissionsServiceOutput output = new GetPermissionsServiceOutput();
        Long curversion = objectFinal.getDataEffectiveVersion();
        List<UserApiDto> curList = usersMapper.GetUsersAPI(input.getAppCode(), "", "", "", input.getUserCode(), curversion);
        if (curList != null && curList.size() > 0) {
            UserApiDto cur = curList.get(0);
            List<String> orgIds = new ArrayList<>();
            for (OrgDto org : cur.getUserOrgs()) {
                orgIds.add(org.getId());
            }
            for (JobDto job : cur.getUserJobs()) {
                if (job.getOrg() != null)
                    orgIds.add(job.getOrg().getId());
            }
            List<String> dataIds = new ArrayList<>();
            if (orgIds != null && orgIds.size() > 0) {
                //获取当前所属部门的上级部门  岗位所在部门
                List<Orgs> orgs = orgsMapper.getUserByIds(orgIds);

                for (Orgs org : orgs) {
                    dataIds.add(org.getId());
                }
            }

            for (OrgDto org : cur.getUserOrgs()) {
                dataIds.add(org.getId());
            }
            for (RoleDto role : cur.getUserRoles()) {
                dataIds.add(role.getId());
            }

            dataIds.add(cur.getId());

            //所有权限
            List<PermissionsDto> ls = permissionsMapper.GetPermissions(dataIds, input.getAppCode());
            //菜单功能权限
            List<PermissionsDto> menuPermissions = ls.stream().filter(a -> (!a.getPermissionType().equals("应用")) && a.getParentId() != null).collect(Collectors.toList());
            Map<String, PermissionsDto> parentPermissionDtoDic = new HashMap<String, PermissionsDto>();
            List<PermissionsDto> permissionDtos = new ArrayList<PermissionsDto>();
            if (menuPermissions != null && menuPermissions.size() > 0) {
                for (int i = 0; i < menuPermissions.size(); i++) {
                    PermissionsDto permissionsDto = new PermissionsDto();
                    BeanUtils.copyProperties(menuPermissions.get(i), permissionsDto);
                    if (menuPermissions.get(i).getParentId() == null || !parentPermissionDtoDic.containsKey(menuPermissions.get(i).getParentId())) {
                        permissionDtos.add(permissionsDto);
                    } else {
                        PermissionsDto parentPermissionDto = parentPermissionDtoDic.get(permissionsDto.getParentId());
                        if (parentPermissionDto.getChildren() == null) {
                            parentPermissionDto.setChildren(new ArrayList<PermissionsDto>());
                        }
                        parentPermissionDto.getChildren().add(permissionsDto);
                    }
                    parentPermissionDtoDic.put(permissionsDto.getId(), permissionsDto);
                }
            }
            output.setMenuPermissions(permissionDtos);

            List<PermissionsDto> appPermissions = ls.stream().filter(a -> a.getPermissionType().equals("应用") && a.getParentId() != null).collect(Collectors.toList());
            //应用权限
            if (appPermissions.size() > 0 && appPermissions != null) {
                List<String> appIds = new ArrayList<>();
                for (PermissionsDto permissionsDto : appPermissions) {
                    appIds.add(permissionsDto.getId());
                }
                List<AppDto> apps = appsMapper.GetAppsByAppIds(appIds);
                output.setAppsPermissions(apps);
            }


        }

        return output;
    }


    /**
     *  创建人:Coke
     *  备注: 优化版获取权限信息
     *  时间: 2019/4/26 14:03 
     *  参数: 
     */
//    @Cacheable(value = "basewarrant", keyGenerator = "ObjectKey")
    public GetPermissionsServiceOutput GetPermissionsByCoke(GetPermissionsServiceInput input) throws Exception {
        GetPermissionsServiceOutput output = new GetPermissionsServiceOutput();

        GetPermissionsByCokeInput inputCoke = new GetPermissionsByCokeInput();
        inputCoke.setAppCode(input.getAppCode());
        inputCoke.setUserCode(input.getUserCode());
        //所有权限
        List<PermissionsDto> ls = permissionsMapper.GetPermissionsByCoke(inputCoke);
        //菜单功能权限
        List<PermissionsDto> menuPermissions = ls.stream().filter(a -> (!a.getPermissionType().equals("应用")) && a.getParentId() != null).collect(Collectors.toList());
        Map<String, PermissionsDto> parentPermissionDtoDic = new HashMap<String, PermissionsDto>();
        List<PermissionsDto> permissionDtos = new ArrayList<PermissionsDto>();
        if (menuPermissions != null && menuPermissions.size() > 0) {
            for (int i = 0; i < menuPermissions.size(); i++) {
                PermissionsDto permissionsDto = new PermissionsDto();
                BeanUtils.copyProperties(menuPermissions.get(i), permissionsDto);
                if (menuPermissions.get(i).getParentId() == null || !parentPermissionDtoDic.containsKey(menuPermissions.get(i).getParentId())) {
                    permissionDtos.add(permissionsDto);
                } else {
                    PermissionsDto parentPermissionDto = parentPermissionDtoDic.get(permissionsDto.getParentId());
                    if (parentPermissionDto.getChildren() == null) {
                        parentPermissionDto.setChildren(new ArrayList<PermissionsDto>());
                    }
                    parentPermissionDto.getChildren().add(permissionsDto);
                }
                parentPermissionDtoDic.put(permissionsDto.getId(), permissionsDto);
            }
        }
        output.setMenuPermissions(permissionDtos);

        List<PermissionsDto> appPermissions = ls.stream().filter(a -> a.getPermissionType().equals("应用") && a.getParentId() != null).collect(Collectors.toList());
        //应用权限
        if (appPermissions.size() > 0 && appPermissions != null) {
            List<String> appIds = new ArrayList<>();
            for (PermissionsDto permissionsDto : appPermissions) {
                appIds.add(permissionsDto.getId());
            }
            List<AppDto> apps = appsMapper.GetAppsByAppIds(appIds);
            output.setAppsPermissions(apps);
        }
        return output;
    }


    /**
     *  创建人:Coke
     *  备注: 查询菜单信息
     *  时间: 2019/4/26 14:13
     *  参数: 
     */
//    @Transactional
    public GetMenusOutput GetMenus(GetMenusInput input) throws Exception {
        GetMenusOutput output = new GetMenusOutput();
        GetPermissionsServiceInput permissionsServiceInput = new GetPermissionsServiceInput();
        permissionsServiceInput.setAppCode(input.getAppCode());
        permissionsServiceInput.setUserCode(input.getUserCode());
        List<PermissionsDto> permissions = permissionService.GetPermissionsByCoke(permissionsServiceInput).getMenuPermissions();
        List<MenuDto> menus = new ArrayList<>();
        ls(permissions, menus);

        menus.sort((o1, o2) -> {
            if (o1.getLevel() > o2.getLevel()) {
                return 1;
            } else if (o1.getLevel() < o2.getLevel()) {
                return -1;
            } else {
                if (o1.getSort() == null) {
                    return 1;
                }
                if (o2.getSort() == null) {
                    return -1;
                }
                if (o1.getSort() > o2.getSort()) {
                    return 1;
                } else if (o1.getSort() == o2.getSort()) {
                    return 0;

                } else {
                    return -1;
                }
            }


        });

        Map<String, MenuDto> parentMenuDtoDic = new HashMap<String, MenuDto>();
        List<MenuDto> menuDtos = new ArrayList<MenuDto>();
        if (menus != null && menus.size() > 0) {
            for (int i = 0; i < menus.size(); i++) {
                MenuDto menuDto = new MenuDto();
                BeanUtils.copyProperties(menus.get(i), menuDto);
                if (menus.get(i).getParentId() == null || !parentMenuDtoDic.containsKey(menus.get(i).getParentId())) {
                    menuDtos.add(menuDto);
                } else {
                    MenuDto parentMenuDto = parentMenuDtoDic.get(menuDto.getParentId());
                    if (parentMenuDto.getChildren() == null) {
                        parentMenuDto.setChildren(new ArrayList<MenuDto>());
                    }
                    parentMenuDto.getChildren().add(menuDto);
                }
                parentMenuDtoDic.put(menuDto.getId(), menuDto);
            }
        }
        output.setMenus(menuDtos);
        return output;
    }

    private void ls(List<PermissionsDto> permissions, List<MenuDto> menus) {
        if (permissions != null && permissions.size() > 0) {
            for (PermissionsDto permissionsDto : permissions) {
                if (permissionsDto.getPermissionType().equals("菜单")) {
                    MenuDto menu = new MenuDto();
                    menu.setId(permissionsDto.getId());
                    menu.setKey(permissionsDto.getPermissionCode());
                    menu.setName(permissionsDto.getPermissionName());
                    menu.setUrl(permissionsDto.getUrl());
                    menu.setParentId(permissionsDto.getParentId());
                    menu.setIcon(permissionsDto.getIcon());
                    menu.setSort(permissionsDto.getListOrder());
                    menu.setLevel(permissionsDto.getLevel());
                    menus.add(menu);
                    if (permissionsDto.getChildren() != null && permissionsDto.getChildren().size() > 0) {
                        ls(permissionsDto.getChildren(), menus);
                    }
                }
            }
        }

    }
}
